﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace NetworkingLibrary.Messages.Java
{
    public interface JavaDataObject
    {
        byte[] ToBytes();
        void FromBytes(byte[] Data);
    }

    public static class JavaDataObjectHandler
    {
        private static List<Type> typeIds = null;
        public static List<Type> TypeIds
        {
            get
            {
                if (typeIds == null)
                {
                    typeIds = new Type[]
                    {
                        typeof(JavaInt),
                        typeof(JavaString),
                        typeof(JavaDisconnect)
                    }.ToList();
                }
                return typeIds;
            }
            set
            {
                typeIds = value;
            }
        }

        public static byte[] ToBytes(JavaDataObject Obj)
        {
            List<byte> RetBytes = BitConverter.GetBytes(TypeIds.IndexOf(Obj.GetType())).ToList();
            RetBytes.AddRange(Obj.ToBytes());
            return RetBytes.ToArray();
        }
        public static JavaDataObject FromBytes(byte[] ObjData)
        {
            List<byte> DataBytes = ObjData.ToList();
            byte[] TypeIDBytes = DataBytes.Take(4).ToArray();
            DataBytes.RemoveRange(0, 4);
            int TypeID = BitConverter.ToInt32(TypeIDBytes, 0);

            JavaDataObject TheObj = (JavaDataObject)TypeIds[TypeID].GetConstructor(new Type[] { typeof(byte[]) }).Invoke(new object[] { DataBytes.ToArray() });
            return TheObj;
        }
    }
    public class JavaDisconnect : JavaDataObject
    {
        public JavaDisconnect()
        {
        }
        public JavaDisconnect(byte[] valueData)
        {
            FromBytes(valueData);
        }

        public virtual byte[] ToBytes()
        {
            return new byte[0];
        }
        public virtual void FromBytes(byte[] Data)
        {
        }
    }
    public class JavaInt : JavaDataObject
    {
        public int Value;

        public JavaInt(int value)
        {
            Value = value;
        }
        public JavaInt(byte[] valueData)
        {
            FromBytes(valueData);
        }

        /// <summary>
        /// This code assumes little endian data.
        /// </summary>
        /// <returns></returns>
        public virtual byte[] ToBytes()
        {
            return BitConverter.GetBytes(Value);
        }
        /// <summary>
        /// This code assumes little endian data.
        /// </summary>
        /// <returns></returns>
        public virtual void FromBytes(byte[] Data)
        {
            Value = BitConverter.ToInt32(Data, 0);
        }

        public override string ToString()
        {
            return Value.ToString();
        }
    }

    public class JavaString : JavaDataObject
    {
        public string Value;

        public JavaString(string value)
        {
            Value = value;
        }
        public JavaString(byte[] valueData)
        {
            FromBytes(valueData);
        }

        public virtual byte[] ToBytes()
        {
            return System.Text.Encoding.UTF8.GetBytes(Value);
        }
        public virtual void FromBytes(byte[] Data)
        {
            Value = System.Text.Encoding.UTF8.GetString(Data);
        }

        public override string ToString()
        {
            return Value;
        }
    }
}
